#include <bits/stdc++.h>
#include <cstdio>
#define double long double
using namespace std;
const int N = 1e5 + 5;

struct car
{
    int d, v, a;
} cars[N];

struct node
{
    int max;
    int point;
    int lazy;
} tr[N * 4];

int T;
int n, m, L, V;
int p[N];
bool AorB = 1;
vector<int> ps[N];
int ca[N][3];

void pushdown(int u, int l, int r)
{
    if (!tr[u].lazy)
        return;

    int x = tr[u].lazy;
    tr[u].lazy = 0;
    int lson = u * 2;
    int rson = u * 2 + 1;
    tr[lson].max += x;
    tr[lson].lazy += x;
    tr[rson].max += x;
    tr[rson].lazy += x;
    return;
}

void build(int u,int l,int r)
{
    if(l>r)
        return;
    if(l==r)
    {
        tr[u].point=l;
        return;
    }

    int mid = (l + r) / 2;
    build(u * 2, l, mid);
    build(u * 2 + 1, mid + 1, r);
    tr[u].point=l;
}

void update(int L, int R, int x, int u, int l, int r)
{
    if (L <= l && r <= R)
    {
        tr[u].max += x;
        tr[u].lazy += x;
        return;
    }

    pushdown(u, l, r);

    int mid = (l + r) / 2;
    if (L <= mid)
        update(L, R, x, u * 2, l, mid);
    if (mid + 1 <= R)
        update(L, R, x, u * 2 + 1, mid + 1, r);

    if (tr[u * 2].max > tr[u * 2 + 1].max)
    {
        tr[u].max = tr[u * 2].max;
        tr[u].point = tr[u * 2].point;
    }
    else
    {
        tr[u].max = tr[u * 2 + 1].max;
        tr[u].point = tr[u * 2 + 1].point;
    }
}

int main()
{
    freopen("detect.in", "r", stdin);
    freopen("detect.out", "w", stdout);
    scanf("%d", &T);
    while (T--)
    {
        int ans = 0;
        int cnt = 0;
        scanf("%d%d%d%d", &n, &m, &L, &V);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d%d%d", &cars[i].d, &cars[i].v, &cars[i].a);
            if (cars[i].a < 0)
                AorB = 0;
        }

        for (int i = 1; i <= m; i++)
            scanf("%d", &p[i]);

        sort(p + 1, p + m + 1);
        for(int i=1;i<=n*4;i++)
            tr[i].lazy=tr[i].max=tr[i].point=0;
        build(1,1,n);
        for(int i=0;i<=m;i++)
            ps[i].clear();

        for (int i = 1; i <= n; i++)
        {
            int a = cars[i].a;
            int v = cars[i].v;
            int d = cars[i].d;
            if (a == 0)
            {
                if (v > V) // chao
                {
                    int p1 = lower_bound(p + 1, p + m + 1, d) - p; // start
                    if (p1 == m + 1)
                        continue;

                    ans++;
                    /* d ~ L jilu */
                    if(AorB)
                        continue;

                    update(p1, m, 1, 1, 1, n);
                    for (int j = p1; j <= m; j++)
                        ps[j].push_back(i);
                    ca[i][1] = p1;
                    ca[i][2] = m;
                }
                else
                {
                    //bu chao
                }
            }
            else if (a > 0)
            {
                if (v > V)
                {
                    int p1 = lower_bound(p + 1, p + m + 1, d) - p;
                    if (p1 == m + 1)
                        continue;

                    ans++;
                    /* d ~ L jilu */
                    if(AorB)
                        continue;

                    update(p1, m, 1, 1, 1, n);
                    for (int j = p1; j <= m; j++)
                        ps[j].push_back(i);
                    ca[i][1] = p1;
                    ca[i][2] = m;
                }
                else // v <= V
                {
                    // zhao p
                    double dis_max = (V * V - v * v) / 2 / a;
                    int di = (int)(dis_max) + d;
                    int p1 = upper_bound(p + 1, p + m + 1, di) - p;
                    if (p1 == m + 1)
                        continue;

                    ans++;
                    /* p1 ~ L jilu */

                    if(AorB)
                        continue;

                    update(p1, m, 1, 1, 1, n);
                    for (int j = p1; j <= m; j++)
                        ps[j].push_back(i);
                    ca[i][1] = p1;
                    ca[i][2] = m;
                }
            }
            else if (a < 0) // UNDO
            {
                if (v <= V)
                {
                    // bu chao
                }
                else // v > V
                {
                    // zhao p
                    double dis_max = (V * V - v * v) / 2 / (a); // bu chao de wei zhi
                    int di = ceil(dis_max);
                    di += d;
                    int p1 = lower_bound(p + 1, p + m + 1, d) - p;
                    //int p2=p1-1;
                    //for(int j=p1;j<=m;j++)
                    //    if(sqrt((double)v*v+2*a*(p[j]-p[p1]))>V)
                    //        p2=j;
                    int p2 = lower_bound(p + 1, p + m + 1, di) - p;
                    p2--;
                    //if (p1 == m + 1 || p1 == p2)
                    if (p1 > p2 || p1 == m + 1) // mei jian cha dao
                        continue;

                    ans++;
                    /* [p1 ~ p2] jilu */
                    update(p1, p2, 1, 1, 1, n);
                    for (int j = p1; j <= p2; j++)
                        ps[j].push_back(i);
                    ca[i][1] = p1;
                    ca[i][2] = p2;
                }
            }
        }

        if (AorB)
        {
            if (ans)
                cnt = m - 1;
            else
                cnt = m;
        }
        else
        {
            cnt = m;
            while (tr[1].max>0)
            {
                cnt--;
                int p = tr[1].point;
                //cout<<p<<endl;
                for(int c:ps[p])
                    update(ca[c][1],ca[c][2],-1,1,1,n);
            }
        }

        printf("%d %d\n", ans, cnt);
    }

    return 0;
}
